/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.mail163.email;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.text.Spannable;
import android.text.SpannableStringBuilder;

import com.mail163.email.mail.transport.Rfc822Output;
import com.mail163.email.provider.EmailContent.Attachment;

/**
 * A class for annotating a CharSequence with spans to convert textual emoticons
 * to graphical ones.
 */
public class SmileyParser {
    // Singleton stuff
    private static SmileyParser sInstance;
    public static SmileyParser getInstance() { return sInstance; }
    public static void init(Context context) {
        sInstance = new SmileyParser(context);
    }

    private final Context mContext;
    private final String[] mSmileyTexts;
    private final Pattern mPattern;
    private final HashMap<String, Integer> mSmileyToRes;

    private SmileyParser(Context context) {
        mContext = context;
        mSmileyTexts = mContext.getResources().getStringArray(DEFAULT_SMILEY_TEXTS);
        mSmileyToRes = buildSmileyToRes();
        mPattern = buildPattern();
    }

    static class Smileys {
        private static final int[] sIconIds = {
            R.drawable.emoji_e415,
            R.drawable.emoji_e056, 
            R.drawable.emoji_e057,
            R.drawable.emoji_e414, 
            R.drawable.emoji_e405,
            R.drawable.emoji_e106, 
            R.drawable.emoji_e418,
            R.drawable.emoji_e417, 
            R.drawable.emoji_e40d,
            R.drawable.emoji_e40a, 
            R.drawable.emoji_e404,
            R.drawable.emoji_e105, 
            R.drawable.emoji_e409,
            R.drawable.emoji_e40e, 
            R.drawable.emoji_e402,
            R.drawable.emoji_e108
        };

        public static int E415 = 0;
        public static int E056 = 1;
        public static int E057 = 2;
        public static int E414 = 3;
        public static int E405 = 4;
        public static int E106 = 5;
        public static int E418 = 6;
        public static int E417 = 7;
        public static int E40d = 8;
        public static int E40a = 9;
        public static int E404 = 10;
        public static int E105 = 11;
        public static int E409 = 12;
        public static int E40e = 13;
        public static int E402 = 14;
        public static int E108 = 15;

        public static int getSmileyResource(int which) {
            return sIconIds[which];
        }
    }

    // NOTE: if you change anything about this array, you must make the corresponding change
    // to the string arrays: default_smiley_texts and default_smiley_names in res/values/arrays.xml
    public static final int[] DEFAULT_SMILEY_RES_IDS = {
        Smileys.getSmileyResource(Smileys.E415),                //  0
        Smileys.getSmileyResource(Smileys.E056),                  //  1
        Smileys.getSmileyResource(Smileys.E057),              //  2
        Smileys.getSmileyResource(Smileys.E414),  //  3
        Smileys.getSmileyResource(Smileys.E405),            //  4
        Smileys.getSmileyResource(Smileys.E106),              //  5
        Smileys.getSmileyResource(Smileys.E418),              //  6
        Smileys.getSmileyResource(Smileys.E417),                 //  7
        Smileys.getSmileyResource(Smileys.E40d),          //  8
        Smileys.getSmileyResource(Smileys.E40a),        //  9
        Smileys.getSmileyResource(Smileys.E404),          //  10
        Smileys.getSmileyResource(Smileys.E105),                //  11
        Smileys.getSmileyResource(Smileys.E409),            //  12
        Smileys.getSmileyResource(Smileys.E40e),               //  13
        Smileys.getSmileyResource(Smileys.E402),      //  14
        Smileys.getSmileyResource(Smileys.E108),             //  15
    };

    public static final int DEFAULT_SMILEY_TEXTS = R.array.default_smiley_texts;
//    public static final int DEFAULT_SMILEY_NAMES = R.array.default_smiley_names;

    /**
     * Builds the hashtable we use for mapping the string version
     * of a smiley (e.g. ":-)") to a resource ID for the icon version.
     */
    private HashMap<String, Integer> buildSmileyToRes() {
        if (DEFAULT_SMILEY_RES_IDS.length != mSmileyTexts.length) {
            // Throw an exception if someone updated DEFAULT_SMILEY_RES_IDS
            // and failed to update arrays.xml
            throw new IllegalStateException("Smiley resource ID/text mismatch");
        }

        HashMap<String, Integer> smileyToRes =
                            new HashMap<String, Integer>(mSmileyTexts.length);
        for (int i = 0; i < mSmileyTexts.length; i++) {
            smileyToRes.put(mSmileyTexts[i], DEFAULT_SMILEY_RES_IDS[i]);
        }

        return smileyToRes;
    }

    /**
     * Builds the regular expression we use to find smileys in {@link #addSmileySpans}.
     */
    private Pattern buildPattern() {
        // Set the StringBuilder capacity with the assumption that the average
        // smiley is 3 characters long.
        StringBuilder patternString = new StringBuilder(mSmileyTexts.length * 3);

        // Build a regex that looks like (:-)|:-(|...), but escaping the smilies
        // properly so they will be interpreted literally by the regex matcher.
        patternString.append('(');
        for (String s : mSmileyTexts) {
            patternString.append(Pattern.quote(s));
            patternString.append('|');
        }
        // Replace the extra '|' with a ')'
        patternString.replace(patternString.length() - 1, patternString.length(), ")");

        return Pattern.compile(patternString.toString());
    }


    /**
     * Adds ImageSpans to a CharSequence that replace textual emoticons such
     * as :-) with a graphical version.
     *
     * @param text A CharSequence possibly containing emoticons
     * @return A CharSequence annotated with ImageSpans covering any
     *         recognized emoticons.
     */
    public CharSequence addSmileySpans(CharSequence text) {
        SpannableStringBuilder builder = new SpannableStringBuilder(text);

        Matcher matcher = mPattern.matcher(text);
        while (matcher.find()) {
            Logs.d(Logs.LOG_TAG, "addSmileySpans  matcher:");
            int resId = mSmileyToRes.get(matcher.group());
            builder.setSpan(new String("<img src = \"cid:"+resId+"\">"),
                            matcher.start(), matcher.end(),
                            Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            Logs.d(Logs.LOG_TAG, "addSmileySpans  matcher::"+builder.toString());
            
        }

        return builder;
    }
    public CharSequence addSmileySpan(CharSequence text) {
        boolean flage = false;
        StringBuffer builder = new StringBuffer(text);
        
        Matcher matcher = mPattern.matcher(text);
        while (matcher.find()) {
            int resId = mSmileyToRes.get(matcher.group());
            Logs.d(Logs.LOG_TAG, "start :"+matcher.start()+" end :"+matcher.end());
            
            builder.replace(matcher.start(),matcher.end(), "<img src = \"cid:"+resId+"\">");
            
            matcher = mPattern.matcher(builder);
            
            Logs.d(Logs.LOG_TAG, "addSmileySpans :"+builder.toString());
            flage = true;
        }
//        if(flage){
//            text = Rfc822Output.htmlSmailParse(builder.toString());
//        }else{
//            
//        }
        
        return builder;
    }
    public ArrayList<Attachment> parseAttachment(Context mContext,CharSequence text) {
        ArrayList<Attachment> mAttachment = new ArrayList<Attachment>();
        Matcher matcher = mPattern.matcher(text);
        while (matcher.find()) {
            int resId = mSmileyToRes.get(matcher.group());
            mAttachment.add(getAttachment(mContext,resId));
        }
        return mAttachment;
    }
  
    public Attachment getAttachment(Context mContext, int res){
        BitmapDrawable d = (BitmapDrawable)mContext.getResources().getDrawable(res);
        d.setBounds(0, 0, d.getIntrinsicWidth() / 2, d.getIntrinsicHeight() / 2);
        Bitmap bitmap = d.getBitmap();
        Attachment attachment = new Attachment();
        attachment.mFileName = String.valueOf(res);
        attachment.mSize = 0;
        attachment.mMimeType = "application/octet-stream";
        attachment.mContentId = String.valueOf(res);
        attachment.mContentBytes = Bitmap2Bytes(bitmap);
        return attachment;
    }
    public String replaceStr(int cid){
        Logs.d(Logs.LOG_TAG, "replaceStr  matcher:"+"<img src = \"cid:"+cid+"\">");
        return new String("<img src = \"cid:"+cid+"\">");
    }
    public byte[] Bitmap2Bytes(Bitmap bm) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
        return baos.toByteArray();
    }
}


